home *** CD-ROM | disk | FTP | other *** search
-
- /* Generated by Interface Builder */
-
- #import "ColumnSelectionHandler.h"
- #import "Plot.h"
- #import "defs.h"
- #import <appkit/Font.h>
- #import <appkit/Panel.h>
- #import <appkit/Window.h>
- #import <appkit/Matrix.h>
- #import <appkit/View.h>
- #import <appkit/ButtonCell.h>
- #import <dpsclient/wraps.h>
- #import <appkit/color.h> /* only for "blanking out" parts of a matrix */
- #import <appkit/graphics.h> /* ditto */
-
- /*
- * The job of this object is to keep the appearance of the Column Selection panel
- * in accord with the state of the program. We do not update the Column Selection
- * panel every time a file is read in, since it is expected that this option will
- * not be heavily used.
- */
-
- @implementation ColumnSelectionHandler
-
- - init
- {
- /*
- * This global variable keeps track of whether the column selection window
- * has ever been displayed. We can avoid updating after the selective
- * file removal if we have never been displayed.
- */
- everVisible = NO;
- return self;
- }
-
-
- /*
- * Arrange to blank out the disabled buttons. The "right" way to do this
- * is probably to have a "RaggedMatrix" class which allows a different
- * number of columns in each row, but there are too many other issues
- * raised by that to deal with right now. Note that having such a class
- * would allow us to correctly deal with the problem of correctly
- * redisplaying the matrix after a resize operation on the window.
- * (We currently get around that problem by making ourself the window's delegate
- * and defining windowDidResize:, and in that method calling
- * perform:with:afterDelay:cancelPrevious, but this is highly suboptimal.)
- */
- - eraseDisabledCells:sender
- {
- int n, j, numrows, numcols, ncurves;
- NXRect r;
-
- [columnMatrix getNumRows:&numrows numCols:&numcols];
- [columnMatrix lockFocus];
- NXSetColor([columnMatrix backgroundColor]);
- /* The NXSetColor call has to come after the lockFocus; otherwise, when
- * this method is called by fixPanel, the color always comes out black
- * even if something else is specifically requested. The weird part is,
- * when this method is called by fixRow, the color is correct when the
- * NXSetColor call is outside the lockFocus.
- */
- for (n=0; n<[plotParam nFiles]; n++) {
- ncurves = [plotParam nCurves:n];
- if (ncurves < numcols-1) {
- for (j=ncurves; j<numcols; j++) {
- [columnMatrix getCellFrame:&r at:n :j+1]; /* note the j+1 */
- NXRectFill(&r);
- }
- }
- }
- [columnMatrix unlockFocus];
- NXPing();
- return self;
- }
-
-
- - removeAll:sender
- /* This method is called by the "remove all files" method of the Plot object. */
- {
- int n, j;
- int numrows, numcols;
- NXSize cellsize, intercell;
- NXCoord dy;
-
- /* Do something only if the window has ever been displayed */
- if (everVisible) {
- [columnMatrix getNumRows:&numrows numCols:&numcols];
- [columnMatrix getCellSize:&cellsize];
- [columnMatrix getIntercell:&intercell];
- /*
- * Wipe out everything.
- */
- dy = (NXCoord)(numrows - 1) * (cellsize.height + intercell.height);
- [columnMatrix moveBy:0.0 :dy];
- /*
- * Before doing renewRows, set the state of all the cells to 0; this is
- * because the renewRows method just recycles the cells, and later on
- * we may find ourselves using a cell which has state=1 when we don't
- * want such a beast. Also enable all cells (paranoia strikes).
- */
- for (n=0; n<numrows; n++) {
- for (j=0; j<numcols; j++) {
- [[columnMatrix cellAt:n :j] setState:0];
- [[columnMatrix cellAt:n :j] setEnabled:YES];
- }
- }
- [columnMatrix renewRows:1 cols:1];
- [columnMatrix sizeToCells];
- [[columnMatrix cellAt:0 :0] setEnabled:YES];
- [[columnMatrix cellAt:0 :0] setType:NX_TOGGLE];
- [[columnMatrix cellAt:0 :0] setState:1];
- [filenameMatrix moveBy:0.0 :dy];
- [filenameMatrix renewRows:1 cols:1];
- [[filenameMatrix cellAt:0 :0] setStringValue:"filename"];
- [filenameMatrix sizeToCells];
- [columnText renewRows:1 cols:1];
- [columnText sizeToCells];
- /* Do some drawing now. Display the view. */
- [[columnMatrix window] display];
- NXPing(); /* needed??? */
- }
- return self;
- }
-
-
- - fixPanel:sender
- /*
- * The select column button activates this method; it is also called from
- * windowDidResize, from Plot.m in postludeToReading, and by the update
- * button on the panel. We have to fix up the column selection panel
- * so that it's correct.
- */
- {
- int n, j;
- int nfilestotal = [plotParam nFiles], maxcols = 0, ncurves;
- char title[80];
- int numrows, numcols;
- BOOL one_on;
- NXSize cellsize, intercell;
- NXCoord dy;
- int * turned_on;
-
- if (everVisible == NO) everVisible = YES;
-
- [columnMatrix getNumRows:&numrows numCols:&numcols];
- [columnMatrix getCellSize:&cellsize];
- [columnMatrix getIntercell:&intercell];
-
- /*
- * We have to create some additional rows and perhaps some additional columns.
- */
- // First figure out how many rows and columns the matrices should have
- for (n=0; n<nfilestotal; n++) {
- maxcols = MAX(maxcols, [plotParam nCurves:n]);
- }
- maxcols++; /* this is the number of columns needed */
- if (numrows != nfilestotal || numcols != maxcols) {
- /* The renewRows:cols: message might have the side effect of setting
- * the state of all the cells of the matrix back to 0; this is undesired,
- * so before changing the number of rows and/or columns in the matrix,
- * make sure we remember which cells in each row were turned on.
- */
- turned_on = (int *)malloc(numrows * sizeof(int)); /* should do error check */
- for (n=0; n<numrows; n++) {
- turned_on[n] = 0; /* cautious initialization */
- for (j=0; j<numcols; j++) {
- if ([[columnMatrix cellAt:n :j] state] == 1) {
- turned_on[n] = j;
- break;
- }
- }
- }
- [columnMatrix renewRows:nfilestotal cols:maxcols];
- for (n=numrows; n<nfilestotal; n++) {
- [[columnMatrix cellAt:n :0] setState:1];
- for (j=1; j<maxcols; j++) {
- [[columnMatrix cellAt:n :j] setState:0];
- }
- }
- /* And now turn cells back on. */
- for (n=0; n<numrows; n++) {
- for (j=0; j<numcols; j++) {
- [[columnMatrix cellAt:n :j] setState:0];
- }
- [[columnMatrix cellAt:n :turned_on[n]] setState:1];
- }
- free((void *)turned_on);
- }
- [columnMatrix sizeToCells];
- dy = (float)(nfilestotal - numrows) * (cellsize.height + intercell.height);
- [columnMatrix moveBy:0.0 :-dy];
- // Some of the cells may come in with type NULLCELL; fix them here
- for (n=0; n<nfilestotal; n++) {
- for (j=0; j<maxcols; j++) {
- [[columnMatrix cellAt:n :j] setEnabled:YES];
- [[columnMatrix cellAt:n :j] setType:NX_TOGGLE];
- }
- }
- // Make sure exactly one button is turned on in each row
- for (n=0; n<nfilestotal; n++) {
- one_on = NO;
- for (j=0; j<maxcols; j++) {
- if ([[columnMatrix cellAt:n :j] state] == 1) {
- one_on = YES;
- break;
- }
- }
- if (!one_on)
- [[columnMatrix cellAt:n :0] setState:1];
- }
- // We surround the [columnMatrix display] and [self eraseDisabledCells]
- // calls with the disableFlushWindow, reenableFlushWindow, and flushWindow
- // calls to prevent the disabled matrix cells from being visible for a long
- // time while they're drawn and then erased.
- [columnPanel disableFlushWindow];
- [columnMatrix display];
- // Disable cells that shouldn't appear.
- for (n=0; n<nfilestotal; n++) {
- ncurves = [plotParam nCurves:n];
- if (ncurves < maxcols-1) {
- for (j=ncurves; j<maxcols; j++) {
- [[columnMatrix cellAt:n :j+1] setType:NX_NULLCELL]; /* note the j+1 */
- [[columnMatrix cellAt:n :j+1] setEnabled:NO]; /* again j+1 */
- }
- }
- }
-
- // We have to put the makeKeyAndOrderFront before the eraseDisabledCells
- // method, because eraseDisabledCells does a lockFocus and lockFocus needs
- // a real window to draw into. We put the makeKeyAndOrderFront here rather
- // than at the beginning of this method because this way the disabled cells
- // of the matrix are visible for a shorter period of time.
- [columnPanel makeKeyAndOrderFront:self];
-
- // Now erase those disabled cells.
- [self eraseDisabledCells:self];
- [columnPanel reenableFlushWindow];
- [columnPanel flushWindowIfNeeded];
- NXPing(); /* needed? */
-
- // That finishes with the columnMatrix; now for the filename Matrix.
- [filenameMatrix renewRows:nfilestotal cols:1];
- for (n=0; n<nfilestotal; n++) {
- if (!strncmp([plotParam filename:(unsigned)n], "pasteboard", 10))
- sprintf(title, "pasteboard");
- else
- sprintf(title, strrchr([plotParam filename:(unsigned)n], '/') + 1);
- [[filenameMatrix cellAt:n :0] setStringValue:title];
- }
- [filenameMatrix sizeToCells];
- [filenameMatrix moveBy:0.0 :-dy];
- [filenameMatrix display];
-
- // And now for the columnText matrix.
- [columnText renewRows:1 cols:maxcols];
- for (j=1; j<=maxcols; j++) {
- sprintf(title, "%d", j);
- [[columnText cellAt:0 :(j-1)] setStringValue:title];
- }
- [columnText sizeToCells];
- [columnText display];
-
- return self;
- }
-
-
- - fixRow:sender
- /* The sender is columnMatrix in the column selection panel; we want to
- * turn off some buttons in the matrix row.
- */
- {
- int row, col, i, prev_col=0, numrows, numcols;
-
- row = [sender selectedRow];
- col = [sender selectedCol];
- [sender getNumRows:&numrows numCols:&numcols];
-
- // Find out what column was previously highlighted:
- for (i=0; i<numcols; i++) {
- if ( [[sender cellAt:row :i] state] == 1 && i != col) {
- prev_col = i;
- break;
- }
- }
- // adjust the matrix
- for (i=0; i<numcols; i++) {
- [ [sender cellAt:row :i] setState:0];
- }
- [ [sender cellAt:row :col] setState:1];
-
- // The disableFlushWindow, reenableFlushWindow, and flushWindow methods
- // bracket the [sender display] and [self eraseDisabledCells] methods, with
- // the result that the disabled cells are not visibly drawn on the screen.
- // This is the way it should be.
- [columnPanel disableFlushWindow];
- [sender display];
- [self eraseDisabledCells:self];
- [columnPanel reenableFlushWindow];
- [columnPanel flushWindowIfNeeded];
-
- // swap the pointers as requested
- [plotParam swapColumns:prev_col :col forFileNumber:row];
- return self;
- }
-
- /*
- * We call fixPanel here, rather than eraseDisabledCells (which is more
- * logical), because for some reason eraseDisableCells doesn't seem to work
- * properly! The method fixPanel: does a lot more work than is really
- * needed. Sigh... This should all be cleaned up.
- */
- - windowDidResize:sender
- {
- [self perform:@selector(fixPanel:)
- with:self
- afterDelay:1 /* wait 0.001 second */
- cancelPrevious:YES];
- return self;
- }
-
-
- /*
- * This is called by the selective file removal code in Plot.m.
- */
- - update:sender
- {
- int n, nfilestotal = [plotParam nFiles], num_removed = 0;
- NXSize cellsize, intercell;
- NXCoord dy;
-
- /* Do something only if the window has ever been displayed */
- if (everVisible) {
- [columnMatrix getCellSize:&cellsize];
- [columnMatrix getIntercell:&intercell];
- /*
- * Count down the file removal panel, removing rows as needed.
- */
- for (n = nfilestotal-1; n>=0; n--) {
- if ([[fileRemovalButtons cellAt:n :0] state] == 1) {
- /* This file is to be removed. */
- num_removed++;
- [columnMatrix removeRowAt:n andFree:YES];
- [filenameMatrix removeRowAt:n andFree:YES];
- }
- }
- [columnMatrix sizeToCells];
- [filenameMatrix sizeToCells];
- if (num_removed > 0) {
- dy = (NXCoord)(num_removed) * (cellsize.height + intercell.height);
- [columnMatrix moveBy:0.0 :dy];
- [filenameMatrix moveBy:0.0 :dy];
- }
- /* Do some drawing now. Display the view. */
- [[columnMatrix window] display];
- NXPing(); /* needed??? */
- }
-
- return self;
- }
-
-
-
- @end
-